/**
 * @class 天文学星域范围实体
 * @author DuskyHuang 圣子
*/

import { _decorator, Component, Color, MeshRenderer, Vec4, Material, renderer } from 'cc';
import { utils } from 'cfw';
import { attenuate } from 'algorithms';
import { SceneGraph } from 'const';
import { setLabelStyle } from 'helpers';
import { CosmosProxy, GizmosProxy, ui } from 'proxies';
import { CelestialLabel } from '../ui/items/celestial-label';
const { ccclass } = _decorator;

@ccclass('cocosmos.CylinderScope')
export class CylinderScope extends Component {

    protected onLoad(): void { this._init()._loadParams(); }

    protected lateUpdate(): void {
        const { x, y, z } = this.node.worldScale;
        const scale = (x + y + z) / 3;
        const att = attenuate(scale, ScopeAtt);
        this._lineStrength(att);
        if (ui.showNotes && att > 0 && scale < 1.2) {
            this._title.target = this._desc.target = this.node;
            this._title.alpha = this._desc.alpha = att;
        } else {
            this._title.target = this._desc.target = null;
        }
    }

    protected onDisable(): void {
        this._title.target = this._desc.target = null;
    }

    private _init(): this {
        this._mat = this.getComponent(MeshRenderer)!.material;
        this._mat_line = this.node.getChildByName('lines')!.getComponent(MeshRenderer)!.material;
        this._handle_line = this._mat_line!.passes[0].getHandle('mainColor');
        this._title = setLabelStyle(CelestialLabel.claim('ruler', 'scope.title'), 'ruler', 'title');
        this._desc = setLabelStyle(CelestialLabel.claim('ruler', 'scope.desc'), 'ruler');
        const cam = utils.findCamera(COSMOS, MAIN);
        [this._title, this._desc].forEach(label => label.camera = cam);
        this._title.setOffset(0, this.node.scale.y * 0.65, 0);
        this._desc.setOffset(0, this.node.scale.y * 0.55, 0);
        return this;
    }

    private _loadParams(): void {
        const name = this.node.parent.name;
        const Scalar = CosmosProxy.Scopes[name] as scope;
        const [sx, sy, sz] = Scalar[3] ?? [1, 1, 1];
        this.node.setScale(sx, sy, sz);
        if (Scalar?.[4]) {
            const { x, y, z } = Scalar[4];
            this.node.setPosition(x, y, z);
        }
        this.node.name = 'Scope of ' + name;
        this._color.set(ScopeColor[name] ?? Color.WHITE);
        this._mat.setProperty('mainColor', this._setAlpha(SCOPE_ALPHA));
        this._mat.setProperty('scaleAtte', v4a.set(...ScopeAtt));
        this._lineStrength(0);
        // const [TITLE, DESC] = ScopeTips[name];
        // this._title.string = TITLE;
        // this._desc.string = DESC;
        this._title.key = `scopes@${name}-title`;
        this._desc.key = `scopes@${name}-desc`;
    }

    private _lineStrength(alpha: num.pct): void {
        this._mat_line.passes[0].setUniform(this._handle_line, this._setAlpha(alpha));
    }

    private _setAlpha(ratio: num.ratio): Color {
        color.set(this._color);
        color.r *= ratio;
        color.g *= ratio;
        color.b *= ratio;
        return color;
    }

    private _mat: Material | renderer.MaterialInstance;
    private _mat_line: Material | renderer.MaterialInstance;
    private _handle_line: number;
    private _title: CelestialLabel;
    private _desc: CelestialLabel;

    private _color: Color = new Color;
}

const { COSMOS, Cameras: { MAIN } } = SceneGraph;
const color = new Color;
const v4a = new Vec4;
const SCOPE_ALPHA = 0.3;
const { ScopeColor, ScopeAtt } = GizmosProxy;